package com.jy.rhin.facade.ws.basic.wsEntry;

import com.jy.rhin.application.registration.ValueSetService;
import com.jy.rhin.config.RhinFaultCode;
import com.jy.rhin.config.RhinWSAction;
import com.jy.rhin.facade.ws.basic.wsEntry.exception.*;
import com.jy.rhin.support.aspect.AuditLog;
import com.jy.rhin.support.util.XmlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.jws.WebService;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Slf4j
@WebService(
        serviceName = "RhinEntryProvider",
        portName = "RhinEntryProviderPort",
        targetNamespace = "urn:hl7-org:v3",
        endpointInterface = "com.jy.rhin.facade.ws.basic.wsEntry.RhinEntryProvider")
@Component
public class RhinEntryProviderImpl implements RhinEntryProvider {

    @Autowired
    ValueSetService valueSetProvider;
    @Resource
    ApplicationContext context;

    @AuditLog
    @Override
    public String hipMessageServer(String action, String message) {
        RhinWSAction wsAction = RhinWSAction.getByCode(action);
        if (wsAction == null) {
            return action + "未实现";
        }
        try {
            Class<?> clazzProvider = Class.forName(wsAction.get_interface());
            Class<?> clazzRequest = Class.forName(wsAction.getRequest());
            Object impl = context.getBean(clazzProvider);
            Object req = XmlUtils.xmlStringToObj(message, clazzRequest);
            Method method = clazzProvider.getMethod(wsAction.getMethod(), clazzRequest);
            Object result = method.invoke(impl, req);
            return XmlUtils.objToXmlString(result);
        } catch (ClassNotFoundException | NoSuchMethodException ex) {
            log.error(ex.getMessage(), ex);
            return "接口未实现";
        } catch (IllegalAccessException ex) {
            log.error(ex.getMessage(), ex);
            return "方法执行异常";
        } catch (InvocationTargetException ex) {
            log.error(ex.getMessage(), ex);
            if (ex.getTargetException() instanceof RhinWSException) {
                RhinWSException rsEx = (RhinWSException) ex.getTargetException();
                return XmlUtils.objToXmlString(wsFaultDetail(rsEx));
            }
            return "方法执行异常";
        } catch (RhinWSException ex) {
            log.error(ex.getMessage(), ex);
            return XmlUtils.objToXmlString(wsFaultDetail(ex));
        }
    }

    private FaultDetail wsFaultDetail(RhinWSException ex) {
        FaultDetail fault = new FaultDetail();
        fault.setCode(new Code()
                .setValue(RhinFaultCode.Receiver.getCode())
                .setSubcode(new SubCode().setValue(ex.getErrorType().getCode())));
        fault.setReason(new Reason().setText(ex.getMessage()));
        return fault;
    }
}
